use super::{APP_STATE, FILE_BLOCK_SIZE};
use crate::network_discovery::*;
use crate::{
    file_manager::{FileMeta, FileReader},
    network::TcpClient,
    utils::*,
};
use tauri::{Emitter, Runtime};
use tokio::time::Instant;

use crate::message::*;
use crate::FileManager;
use bincode::serialize;
use std::sync::Arc;
#[tauri::command]
pub fn get_available_ips() -> Vec<String> {
    get_ip_addresses()
}

#[tauri::command]
pub fn get_users() -> Vec<User> {
    let network_discovery = APP_STATE.discover_server.lock();
    let mut result = network_discovery.get_users();
    result
}

#[tauri::command]
pub async fn get_instance_name<R: Runtime>(
    app: tauri::AppHandle<R>,
    window: tauri::Window<R>,
) -> String {
    let guard = APP_STATE.instance_name.lock();
    let result = guard.clone();
    result
}

#[tauri::command]
pub fn rename_discover(new_name: String) {
    *APP_STATE.instance_name.lock() = new_name.clone();
    let target_ip = APP_STATE.target_ip.lock().clone();
    *APP_STATE.discover_server.lock() =
        ServiceDiscovery::new("ZeroTransfer", &new_name, &target_ip, 33445).unwrap();
    let mut discover_server = APP_STATE.discover_server.lock();
    discover_server.start();
}

#[tauri::command]
pub fn change_target_ip(target_ip: String) {
    *APP_STATE.target_ip.lock() = target_ip.clone();
    let instace_name = APP_STATE.target_ip.lock().clone();
    *APP_STATE.discover_server.lock() =
        ServiceDiscovery::new("ZeroTransfer", &instace_name, &target_ip, 33445).unwrap();
    let mut discover_server = APP_STATE.discover_server.lock();
    discover_server.start();
}

#[tauri::command]
pub async fn start_file_transfer<R: Runtime>(
    app: tauri::AppHandle<R>,
    window: tauri::Window<R>,
    file_path: String,
    target_ip: String,
) -> Result<(), String> {
    // 开始传输文件
    // 新建一个tcp客户端
    println!("target_ip: {}", target_ip);
    let client = TcpClient::new(&target_ip, 44556, |data, writer| {
        let app_state = APP_STATE.clone();
        process(app_state, data, writer)
    })
    .await
    .unwrap();
    println!("发送文件元数据");
    let point = APP_STATE.sync_manager.generate_unique_sync_point().await;
    let (net_message, file_info) = build_file_meta_message(file_path.clone(), point);
    if let Err(e) = client.send(&net_message).await {
        return Err(format!("发送元数据无效：{}", e));
    }
    println!("等待反馈");
    let result = APP_STATE.sync_manager.wait_for_sync_point(point).await;
    println!("收到反馈");
    if result != 0 {
        return Ok(());
    }
    // 传输文件的数据
    println!("发送数据");
    // 传输文件数据
    let reader = Arc::new(
        FileReader::new(&file_path)
            .await
            .map_err(|e| e.to_string())?,
    );
    let mut offset = 0u64;
    let file_size = file_info.file_size;

    let start_time = Instant::now();
    let mut last_update_time = start_time;
    let mut last_offset = 0u64;

    while offset < file_size {
        // 计算当前读取长度
        let remaining = file_size - offset;
        let read_length = std::cmp::min(FILE_BLOCK_SIZE as u64, remaining) as usize;

        // 读取数据块
        let data = reader
            .read_at(offset, read_length)
            .await
            .map_err(|e| format!("文件块读取失败: {}", e))?;

        let network_data = build_file_block_message(file_info.file_id, offset, data);

        // 发送处理后的数据
        client
            .send(&network_data)
            .await
            .map_err(|e| format!("数据块发送失败: {}", e))?;

        offset += read_length as u64;

        // 进度更新逻辑
        let current_time = Instant::now();
        let time_since_last_update = current_time.duration_since(last_update_time).as_secs_f64();

        if time_since_last_update >= 0.5 {
            let delta_bytes = offset - last_offset;
            let delta_time = time_since_last_update;

            // 计算传输速度（字节/秒）
            let speed = delta_bytes as f64 / delta_time;
            // 计算剩余字节
            let remaining_bytes = file_size - offset;
            // 计算剩余时间（秒）
            let remaining_time = if speed > 0.0 {
                remaining_bytes as f64 / speed
            } else {
                0.0
            };

            // 转换为更友好的单位（KB/s）
            let speed_kb = speed / 1024.0;

            // 发送更新到前端（每秒最多5次）
            let message = format!(
                "传输进度: 速度 {:.2} KB/s, 剩余时间 {:.1} 秒",
                speed_kb, remaining_time
            );
            if let Err(e) = app.emit("print", message) {
                eprintln!("无法发送进度更新: {}", e);
            }

            // 更新最后一次记录的时间和偏移量
            last_update_time = current_time;
            last_offset = offset;
        }
    }
    println!("文件发送结束");
    // 传输文件结束数据
    let network_data = build_file_end_message(file_info.file_id);
    if let Err(e) = client.send(&network_data).await {
        return Err(format!("发送元数据无效：{}", e));
    }
    println!("等等服务器反馈");
    println!("传输完毕");
    Ok(())
}

fn build_file_meta_message(file_path: String, sync_point: u64) -> (Vec<u8>, FileMeta) {
    // 获取文件信息
    let file_info = FileManager::get_file_info(&file_path).expect("Failed to get file info");

    // 创建 FileMeta 结构体
    let file_meta = FileMetaNetData {
        file_id: file_info.file_id,
        file_name: file_info.file_name.clone(),
        file_size: file_info.file_size,
        request_id: sync_point,
    };

    // 将 FileMeta 序列化为 Vec<u8>
    let serialized_file_meta = serialize(&file_meta).expect("Failed to serialize FileMeta");

    // 创建 NetworkData 结构体
    let network_data = NetworkDataNetData {
        data_type: NetworkDataTypeNetData::FILEMETA,
        data: serialized_file_meta,
    };

    // 使用 bincode 序列化 NetworkData
    (
        serialize(&network_data).expect("Failed to serialize NetworkData"),
        FileMeta::clone_from(&file_info),
    )
}

fn build_file_block_message(file_id: u32, offset: u64, file_data: Vec<u8>) -> Vec<u8> {
    let file_block = FileDataNetData {
        file_id: file_id,
        file_offset: offset,
        file_data: file_data,
    };

    let serialized_file_data = serialize(&file_block).expect("序列化文件块消息失败");

    let network_data = NetworkDataNetData {
        data_type: NetworkDataTypeNetData::FILEDATA,
        data: serialized_file_data,
    };

    serialize(&network_data).expect("无法序列化NetworkData")
}

fn build_file_end_message(file_id: u32) -> Vec<u8> {
    let file_end = FileEndNetData { file_id: file_id };

    let serialized_file_data = serialize(&file_end).expect("序列化文件结束块失败");

    let network_data = NetworkDataNetData {
        data_type: NetworkDataTypeNetData::FILEEND,
        data: serialized_file_data,
    };
    serialize(&network_data).expect("无法序列化NetworkData")
}

pub fn build_reply(request_id: u64, reply: u64) -> Vec<u8> {
    let file_reply = FileReplyNetData {
        request_id: request_id,
        reply: reply,
    };

    let serialized_file_data = serialize(&file_reply).expect("序列化回复失败");

    let network_data = NetworkDataNetData {
        data_type: NetworkDataTypeNetData::FILEREPLY,
        data: serialized_file_data,
    };
    serialize(&network_data).expect("无法序列化networkData")
}
